package com.mccabe;

import java.io.*;
import java.util.*;
import java.net.*;
import java.lang.*;

/* new classes for coverage server functionality */

class Client
{
    //private member variables
    private String     m_strServer;
    private int        m_nRemotePort;
    private boolean    m_bSendOnly;
    private boolean    m_bLibLoad;
    private boolean    m_bSocketInit;
    private boolean    m_bConnStatus;
    private String     NEWLINE = String.valueOf('\n');
    private Socket     m_sClient;
    private BufferedReader      m_input; //QA11301
    private DataOutputStream    m_output;
    private String     m_strErrorMsg;
    private boolean    m_bConnDropped;
    private int        m_nErrorCode;

    boolean cs_sync = false;    //QA11399

    // Static constants
    public static final int        CONNECTFAILURE = 10;
    public static final int        SENDFAILURE = 20;
    public static final int        DISCONNECTFAILURE = 30;
    public static final int        NOCONNECTION = 40;

    // public static covserver_viewer csv = null;

    // QA11399 begin
    public Client(short port, boolean sync)
    {
        m_sClient = null;
        m_nRemotePort = port;
        m_strServer = "localhost";
        m_bConnStatus = false;
        cs_sync = sync;
    }    // QA11399 end

    /* public void add_cs (covserver_viewer csv)
    {
        this.csv = csv;
    } */

    public void setServer(String svr)
    {
        m_strServer = svr;
    }

    public void setRemotePort(int port)
    {
        m_nRemotePort = port;
    }

    public void setCommunicationMode(boolean mode)
    {
        m_bSendOnly = mode;
    }

    public boolean get_response ()
    {
        String line;

        //QA11399
        if (cs_sync == false)
        {
            return (true);
        }
        try
        {
            line = m_input.readLine ();

            if (line.charAt(0) == '\36')
            {
                return (true);
            }
        }
        catch (IOException error) {
            System.err.println("Error reading response code");
        }
        return (false);
    }

    public boolean connect()
    {
        try
        {
            m_bConnStatus = true;
            m_sClient = new Socket(InetAddress.getByName(m_strServer), m_nRemotePort);
            m_input = new BufferedReader(new InputStreamReader(m_sClient.getInputStream()));//QA11301
            m_output = new DataOutputStream(m_sClient.getOutputStream());

            return true;
        }
        catch(IOException err)
        {
            m_nErrorCode = CONNECTFAILURE;
            m_strErrorMsg = "Can't connect to " + m_strServer + ". Make sure the Coverage Server is started";
            m_bConnStatus = false;

            return false;
        }
    }

    public boolean disConnect()
    {
        try
        {
            if(m_bConnStatus)
            {
                sendStream(String.valueOf(900) + String.valueOf('\36') + "Quit");
                m_sClient.close();
                m_bConnStatus = false;
                return true;
            }
            else
            {
                m_nErrorCode = NOCONNECTION;
                m_strErrorMsg = "Please first establish the connection";
                return false;
            }
        }
        catch(IOException err)
        {
            m_nErrorCode = DISCONNECTFAILURE;
            m_strErrorMsg = "disConnect failed";
            return false;
        }
    }

    public boolean getChartFile (String source_file)
    {
        int slash_ind;
        String source_dir;

        slash_ind = source_file.lastIndexOf ('\\');

        if (slash_ind == -1)
        {
            slash_ind = source_file.lastIndexOf ('/');
        }

        if (slash_ind >= 0)
        {
            slash_ind++;
            source_dir = source_file.substring (0, slash_ind);

            sendStream (String.valueOf(500) + String.valueOf('\36') + source_dir);

            return (true);
        }
        return (false);
    }

    public boolean getMMFile (String source_file)
    {
        int slash_ind;
        String source_dir;

        slash_ind = source_file.lastIndexOf ('\\');

        if (slash_ind == -1)
        {
            slash_ind = source_file.lastIndexOf ('/');
        }

        if (slash_ind >= 0)
        {
            slash_ind++;
            source_dir = source_file.substring (0, slash_ind);

            sendStream (String.valueOf(600) + String.valueOf('\36') + source_dir);

            return (true);
        }
        return (false);
    }

    public boolean getPTIFile (String source_file)
    {
        int slash_ind;
        String source_dir;

        slash_ind = source_file.lastIndexOf ('\\');

        if (slash_ind == -1)
        {
            slash_ind = source_file.lastIndexOf ('/');
        }

        if (slash_ind >= 0)
        {
            slash_ind++;
            source_dir = source_file.substring (0, slash_ind);

            sendStream (String.valueOf(601) + String.valueOf('\36') + source_dir);

            return (true);
        }
        return (false);
    }

    public boolean getGRAFile (String source_file)
    {
        int slash_ind;
        String source_dir;

        slash_ind = source_file.lastIndexOf ('\\');

        if (slash_ind == -1)
        {
            slash_ind = source_file.lastIndexOf ('/');
        }

        if (slash_ind >= 0)
        {
            slash_ind++;
            source_dir = source_file.substring (0, slash_ind);

            sendStream (String.valueOf(602) + String.valueOf('\36') + source_dir);

            return (true);
        }
        return (false);
    }

    public boolean getEV5File (String source_file)
    {
        int slash_ind;
        String source_dir;

        slash_ind = source_file.lastIndexOf ('\\');

        if (slash_ind == -1)
        {
            slash_ind = source_file.lastIndexOf ('/');
        }

        if (slash_ind >= 0)
        {
            slash_ind++;
            source_dir = source_file.substring (0, slash_ind);

            sendStream (String.valueOf(603) + String.valueOf('\36') + source_dir);

            return (true);
        }

        return (false);
    }

    public boolean getListingFile (String source_file)
    {
        int slash_ind;
        String source_dir;

        slash_ind = source_file.lastIndexOf ('\\');

        if (slash_ind == -1)
        {
            slash_ind = source_file.lastIndexOf ('/');
        }

        if (slash_ind >= 0)
        {
            slash_ind++;
            source_dir = source_file.substring (0, slash_ind);

            sendStream (String.valueOf(705) + String.valueOf('\36') + source_file);

            return (true);
        }
        return (false);
    }

    public boolean sendDirName(String dir)
    {
        boolean rval;

        rval = sendStream(String.valueOf(200) + String.valueOf('\36') + dir);

        if (rval == false)
        {
            return (rval);
        }

        rval = get_response ();
        return (rval);
    }

    public boolean sendFileName(String filename)
    {
        boolean rval;

        rval = sendStream(String.valueOf(300) + String.valueOf('\36') + filename);

        if (rval == false)
        {
            return (rval);
        }

        rval = get_response ();
        return (rval);
    }

    public boolean sendData(String data)
    {
        boolean rval;

        rval = sendStream(String.valueOf(400) + String.valueOf('\36') + data + NEWLINE);

        if (rval == false)
        {
            return (rval);
        }

        rval = get_response ();
        return (rval);
    }

    public boolean sendData(Object data) throws IOException
    {
        boolean rval;

        rval = sendStream(String.valueOf(400) + String.valueOf('\36') + String.valueOf(data) + NEWLINE);

        if (!rval && m_nErrorCode == SENDFAILURE)
        {
            throw new IOException(getErrorMessage());
        }

        if (rval == false)
        {
            return (rval);
        }

        rval = get_response ();
        return (rval);
    }

    public void displayTrace (long val)
    {
        int v1;

        v1 = (int) val;

        displayTrace (v1);
    }

    public void displayTrace (int val)
    {
    /*    if (csv != null)
        {
            csv.update_trace (val);
        } */
    }

    public void setNodeCoverage (int module, int event)
    {
    /*    if (csv != null)
        {
            csv.set_node_coverage (module, event);
        } */
    }

    public void showNodeCoverage (int mod)
    {
    /*    if (csv != null)
        {
            csv.show_node_coverage (mod);
        } */
    }

    public String readline ()
    {
        String line = new String ("");

        try
        {
            line = m_input.readLine ();
        }
        catch(IOException err)
        {
            return (line);
        }
        return (line);
    }

    public boolean sendStream(String stream)
    {
        try
        {
            if(m_bConnStatus)
            {
                m_output.writeUTF(stream + String.valueOf('\35') );
                m_output.flush();
                return true;
            }
            else
            {
                m_nErrorCode = NOCONNECTION;
                m_strErrorMsg = "Please first establish the connection";
                return false;
            }
        }
        catch(IOException err)
        {
            m_nErrorCode = SENDFAILURE;
            m_strErrorMsg = "Can't send data through. Try to reconnect again";
            m_bConnStatus = false;
            if ( !m_bConnDropped )
            {
								System.err.println("McCabe Instrumentation: ERROR: Trace connection lost, possibly disconnected by server.");
								System.err.println("No further coverage will be recorded.");
                m_bConnDropped = true;
            }
            return false;
        }
    }

    public int getErrorCode()
    {
        return m_nErrorCode;
    }

    public String getErrorMessage()
    {
        return m_strErrorMsg;
    }
}

